---
id: auth-control
title: 14. 安全鉴权
sidebar_label: 14. 安全鉴权
---

## 14.1 什么是鉴权

**鉴权实际上就是一种身份认证**。

由用户提供凭据，然后将其与存储在操作系统、数据库、应用或资源中的凭据进行比较。 在授权过程中，如果凭据匹配，则用户身份验证成功，可执行已向其授权的操作。 授权指判断允许用户执行的操作的过程。
也可以将身份验证理解为进入空间（例如服务器、数据库、应用或资源）的一种方式，而授权是用户可以对该空间（服务器、数据库或应用）内的哪些对象执行哪些操作。

### 14.1.1 常见的鉴权方式

- `HTTP Basic Authentication`

这是 `HTTP` 协议实现的基本认证方式，我们在浏览网页时，从浏览器正上方弹出的对话框要求我们输入账号密码，正是使用了这种认证方式

- `Session + Cookie`

利用服务器端的 session（会话）和浏览器端的 cookie 来实现前后端的认证，由于 http 请求时是无状态的，服务器正常情况下是不知道当前请求之前有没有来过，这个时候我们如果要记录状态，就需要在服务器端创建一个会话(seesion),将同一个客户端的请求都维护在各自得会会话中，每当请求到达服务器端的时候，先去查一下该客户端有没有在服务器端创建 seesion，如果有则已经认证成功了，否则就没有认证。

- `Token`

客户端在首次登陆以后，服务端再次接收 `HTTP` 请求的时候，就只认 `Token` 了，请求只要每次把 `Token` 带上就行了，服务器端会拦截所有的请求，然后校验 `Token` 的合法性，合法就放行，不合法就返回 401（鉴权失败）

`Token`验证比较灵活，适用于大部分场景。常用的 `Token` 鉴权方式的解决方案是 `JWT`，`JWT` 是通过对带有相关用户信息的进行加密，加密的方式比较灵活，可以根据需求具体设计。

- `OAuth`

OAuth（开放授权）是一个开放标准，允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息，而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容，为了保护用户数据的安全和隐私，第三方网站访问用户数据前都需要显式的向用户征求授权。我们常见的提供 OAuth 认证服务的厂商有支付宝，QQ,微信。

OAuth 协议又有 1.0 和 2.0 两个版本。相比较 1.0 版，2.0 版整个授权验证流程更简单更安全，也是目前最主要的用户身份验证和授权方式。

## 14.2 如何使用

### 14.2.1 添加 `Cookie` 授权

```cs
// Cookies单独授权
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, b =>
        {
            b.LoginPath = "/Home/Login";
        });
```

### 14.2.2 添加 `Jwt` 授权

```cs
services.AddJwt();
```

:::important 特别注意

`JWT` 鉴权并未包含在 `Fur` 框架中，需要安装 `Fur` 框架提供的 `Fur.Extras.Authentication.JwtBearer` 拓展包。

:::

### 14.2.3 混合授权

```cs
// JWT 和 Cookies 同时授权
services.AddJwt(options =>
{
      options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
      options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, b =>
{
       b.LoginPath = "/Home/Login";
});
```

## 14.3 高级自定义授权

`Fur` 框架提供了非常灵活的高级策略鉴权和授权方式，通过该策略授权方式可以实现任何自定义授权。

### 14.3.1 `AppAuthorizeHandler`

`Fur` 框架提供了 `AppAuthorizeHandler` 策略授权处理程序提供基类，只需要创建自己的 `Handler` 继承它节可。如：`JwtHandler`：

```cs {20,12}
using Fur.Authorization;
using Fur.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.JsonWebTokens;

namespace Fur.Web.Core
{
    /// <summary>
    /// JWT 授权自定义处理程序
    /// </summary>
    public class JwtHandler : AppAuthorizeHandler
    {
        /// <summary>
        /// 请求管道
        /// </summary>
        /// <param name="context"></param>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        public override bool Pipeline(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
        {
            var isValid = context.ValidateJwtBearer(httpContext, out JsonWebToken token);
            if (!isValid) return false;

            // 检查权限
            return CheckAuthorzie(httpContext);
        }

        /// <summary>
        /// 检查权限
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        private static bool CheckAuthorzie(DefaultHttpContext httpContext)
        {
            // 获取权限特性
            var securityDefineAttribute = httpContext.GetMetadata<SecurityDefineAttribute>();
            if (securityDefineAttribute == null) return true;

            return App.GetService<IAuthorizationManager>().CheckSecurity(securityDefineAttribute.ResourceId);
        }
    }
}
```

之后注册 `JwtHandler` 即可：

```cs
services.AddJwt<JwtHandler>();
```

## 14.4 授权特性及全局授权

默认情况下，所有的路由都是允许匿名访问的，所以如果需要对某个 `Action` 或 `Controller` 设定授权访问，只需要在 `Action` 或 `Controller` 贴 `[AppAuthorize]` 或 `[Authorize]` 特性即可。

如果需要对特定的 `Action` 或 `Controller` 允许匿名访问，则贴 `[AllowAnonymous]` 即可。

### 14.4.1 全局授权

```cs
services.AddJwt<JwtHandler>(enableGlobalAuthorize:true);
```

### 14.4.2 匿名访问

如果需要对特定的 `Action` 或 `Controller` 允许匿名访问，则贴 `[AllowAnonymous]` 即可。

## 14.5 反馈与建议

:::note 与我们交流

给 Fur 提 [Issue](https://gitee.com/monksoul/Fur/issues/new?issue)。

:::

---

:::note 了解更多

想了解更多 `鉴权授权` 知识可查阅 [ASP.NET Core - 安全和标识](https://docs.microsoft.com/zh-cn/aspnet/core/security/?view=aspnetcore-5.0) 章节。

:::
